package com.meilingcloud.activiti.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.Page;
import com.meilingcloud.activiti.domain.ActWfFormData;
import com.meilingcloud.activiti.domain.dto.ActFormDataSaveDto;
import com.meilingcloud.activiti.domain.dto.ActTaskDto;
import com.meilingcloud.activiti.service.IActTaskService;
import com.meilingcloud.activiti.service.IActWfFormDataService;
import com.meilingcloud.common.core.page.PageDomain;
import com.meilingcloud.common.utils.DateUtils;
import com.meilingcloud.common.utils.SecurityUtils;
import com.meilingcloud.system.domain.SysCustomForm;
import com.meilingcloud.system.service.ISysCustomFormService;
import lombok.RequiredArgsConstructor;
import org.activiti.api.runtime.shared.query.Order;
import org.activiti.api.runtime.shared.query.Pageable;
import org.activiti.api.task.model.Task;
import org.activiti.api.task.model.builders.TaskPayloadBuilder;
import org.activiti.api.task.runtime.TaskRuntime;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;

@RequiredArgsConstructor(onConstructor_ = @Autowired)
@Service
public class ActTaskServiceImpl implements IActTaskService {

    private final RepositoryService repositoryService;
    private final TaskRuntime taskRuntime;
    private final TaskService taskService;
    private final RuntimeService runtimeService;
    private final IActWfFormDataService actWfFormdataService;
    private final ISysCustomFormService sysCustomFormService;

    @Override
    public Page<ActTaskDto> selectProcessDefinitionList(PageDomain pageDomain) {
        Page<ActTaskDto> list = new Page<>();
        org.activiti.api.runtime.shared.query.Page<Task> pageTasks = taskRuntime.tasks(
                Pageable.of((pageDomain.getPageNum() - 1) * pageDomain.getPageSize(), pageDomain.getPageSize(),
                        Order.by("createdDate", Order.Direction.DESC)));
        List<Task> tasks = pageTasks.getContent();
        int totalItems = pageTasks.getTotalItems();
        list.setTotal(totalItems);
        if (totalItems != 0) {
            Set<String> processInstanceIds = tasks.stream().map(Task::getProcessInstanceId).collect(Collectors.toSet());
            List<ProcessInstance> processInstanceList = runtimeService.createProcessInstanceQuery().processInstanceIds(processInstanceIds).list();
            List<ActTaskDto> actTaskDtos = tasks.stream()
                    .map(t -> new ActTaskDto(t, processInstanceList.stream().filter(pi -> t.getProcessInstanceId().equals(pi.getId())).findAny().get()))
                    .sorted(Comparator.comparing(ActTaskDto::getCreateTime).reversed())
                    .collect(Collectors.toList());
            list.addAll(actTaskDtos);
        }
        return list;
    }

    @Override
    public Map<String, List<String>> formDataShow(String taskId) {
        Map<String, List<String>> map = new HashMap<>();

        //获取表单信息
        org.activiti.engine.task.Task taskDef = taskService.createTaskQuery()
                .taskId(taskId)
                .singleResult();
        UserTask userTask = (UserTask) repositoryService.getBpmnModel(taskDef.getProcessDefinitionId())
                .getFlowElement(taskDef.getTaskDefinitionKey());

        SysCustomForm customForm = sysCustomFormService.getOne(new QueryWrapper<SysCustomForm>().eq("form_key", taskDef.getFormKey()));
        if (customForm != null) {
            map.put(taskDef.getFormKey(), Collections.singletonList(customForm.getFormJson()));
        } else {
            map.put(taskDef.getFormKey(), null);
        }
        return map;
    }

    @Override
    public boolean formDataSave(String taskId, ActFormDataSaveDto params) throws ParseException {
        String optUserName = SecurityUtils.getUsername();

        Task task = taskRuntime.task(taskId);
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();

        if (task.getAssignee() == null) {
            //代理人没有的话，则当前用户接收
            taskRuntime.claim(
                    TaskPayloadBuilder.claim()
                            .withTaskId(task.getId())
                            .withAssignee(optUserName)
                            .build()
            );
        }
        if (!CollectionUtils.isEmpty(params.getData())) {
            // 带参数完成任务
            task = taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(taskId).withVariables(params.getData()).build());
        } else {
            task = taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(taskId).build());
        }

        // 参数信息写入数据库
        ActWfFormData formdata = new ActWfFormData();
        formdata.setCreateBy(task.getAssignee());
        formdata.setCreateTime(DateUtils.getNowDate());
        // 这个一直是null
        formdata.setBusinessKey(task.getBusinessKey());

        formdata.setBusinessKey(processInstance.getBusinessKey());
        formdata.setFormKey(task.getFormKey());
        formdata.setTaskNodeName(task.getName());
        formdata.setFormData(JSON.toJSONString(params.getData()));
        formdata.setFormDesc(JSON.toJSONString(params.getDesc()));

        return actWfFormdataService.save(formdata);
    }

    /**
     * 批量审批
     *
     * @param taskIds 任务id
     * @param params  批处理表单数据保存dto
     * @return boolean
     */
    @Override
    @Transactional
    public boolean batchFormDataSave(List<String> taskIds, ActFormDataSaveDto params) {
        String optUserName = SecurityUtils.getUsername();

        Boolean result = true;
        for (String taskId : taskIds) {
            Task task = taskRuntime.task(taskId);
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();

            if (task.getAssignee() == null) {
                //代理人没有的话，则当前用户接收
                taskRuntime.claim(
                        TaskPayloadBuilder.claim()
                                .withTaskId(task.getId())
                                .withAssignee(optUserName)
                                .build()
                );
            }
            if (!CollectionUtils.isEmpty(params.getData())) {
                // 带参数完成任务
                task = taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(taskId).withVariables(params.getData()).build());
            } else {
                task = taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(taskId).build());
            }

            // 参数信息写入数据库
            ActWfFormData formdata = new ActWfFormData();
            formdata.setCreateBy(task.getAssignee());
            formdata.setCreateTime(DateUtils.getNowDate());
            // 这个一直是null
            formdata.setBusinessKey(task.getBusinessKey());

            formdata.setBusinessKey(processInstance.getBusinessKey());
            formdata.setFormKey(task.getFormKey());
            formdata.setTaskNodeName(task.getName());
            formdata.setFormData(JSON.toJSONString(params.getData()));
            formdata.setFormDesc(JSON.toJSONString(params.getDesc()));

            boolean save = actWfFormdataService.save(formdata);
            if (!save) {
                result = false;
            }
        }

        return result;
    }
}
